package com.slt.android.hooklaunchtt;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;

import com.slt.android.hooklaunchtt.plugin.PluginManager;

/**
 * 我们这里要做的就是MainActivity跳转到一个没有在Manifest中注册的TestActivity
 * 思路:
 * 1.直接跳转肯定是会出错的，(出错的原因是系统在跳转Activity的时候会做一些安全检查等，没配置肯定过不去)
 * 2.我们可以想办法用一个ProxyActivity(已注册)去帮咱们通过检查
 * 3.再在handleLaunchActivity的时候把Intent替换了，启动要偷渡的Intent
 *
 * 细节：
 * 1.首先我们要参与到Activity的启动流程，这件事情里面去。去拦截本身的流程。进入我们自己的动态代理
 * (这里就需要动态代理系统本身的startActivity方法。这个方法是IActivityManager接口的。所以
 * 我们要对startActivity的调用者iamInstance，进行动态代理。这样以后iamInstance执行方法就会回掉我们的invoke方法
 * 详见Util类hookStartActivity方法。)
 * 2.在回调的invoke方法中创建安全的intent去过安检，把不安全的intent。putExtra到里面隐藏
 * 3.再在即将启动activity时，也就是activityThread执行handleLaunchActivity前hook一下
 * (即 1.actvityThread里面 再收到LAUNCH_ACTIVITY这个msg才会执行handleLaunchActivity
 *     2.找到发送LAUNCH_ACTIVITY这个msg的地方，发现是在这个类的scheduleLaunchActivity方法里面。这里面我们看到了intent，那么就可以替换。
 *     3.又由handler的原理知道。如果我们设置了callback，那么就会先执行callback再执行handleMessage方法。这样我们就可在callback中进行替换了
 *     4.详见util里面的hookLaunchActivity方法。
 * )
 * 4.这样就实现了偷渡
 * 总结：
 *     hook两个地方
 *     一 是对ActivityManagerNative.getDefault里面的mInstace设置代理，让mInstace执行的所有方法都经过invoke回调
 *        由于我们代码里直接启动的TestActivity没有配置，所有需要在这里进行替换，替换成proxyActivity的intent代我们经过安检
 *
 *     二 过了安检了，再launch之前hook一下，把我们自身的intent取出来，替换。启动TestActivity
 *
 *  -------------------------------------------------
 *  解决继承自AppcompactActivity崩溃的方法。
 *  1.报错，packageManager报找不到Activity的错误，
 *  2.只需要再多hook一次，通过反射先调用一次getPackageManager方法，就会得到一个packagemanager的缓存。
 *  3.再对iPackageManager进行动态代理，让iPackageManager执行方法都会进我们的invoke回掉。
 *  4.对上述的getActivityInfo方法，返回咱们的CompentName
 */
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void jumpTo(){
        Intent intent = new Intent(this , TestActivity.class);
        startActivity(intent);
    }


    public void click(View view) {
        /*// 启动插件，插件下载好了在内存卡里面
        Intent intent = new Intent();
        // 目前启动肯定报错，类找不到  类怎么办？ 热修复应该能够找到解决方案
        // dex 现在我们加载apk
        intent.setClassName(getPackageName(),
                "com.hc.yaoyiyao.MainActivity");
        // 参数
        intent.putExtra("user_name","Darren");
        startActivity(intent);*/

        // 一定要这样 ---不管是自己的方法还是DroidPlugin，最好都这样
        PackageManager pm =  getPackageManager();
        // 有了apk路径是可以获取apk的包名
        PackageInfo info = pm.getPackageArchiveInfo("apkPath", PackageManager.GET_ACTIVITIES);
        String packageName = info.packageName;
        Intent intent = pm.getLaunchIntentForPackage(packageName);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra("user_name","Darren");
        startActivity(intent);
    }
    public void install(View view){
         PluginManager.install(this,"apkPath");
//        try {
//            int result = PluginManager.install(this, "path");
//            Log.e("TAG","result = "+result);
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }
    }
}
